home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / mac / Technical Documentation / Develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15.sea / Scriptable Database 1.0a15 / Foundation / ResolveObjectSpecifier.cp / ResolveObjectSpecifier.cp
Encoding:
Text File  |  1996-02-20  |  16.8 KB  |  487 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        ResolveObjectSpecifier.cp
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Written by:    Andy Nicholas, Greg Anderson, Chris Bingham, John Rohrlich, Max McFarland, Paul Ossenbruggen, Mike Kobb
  7.  
  8.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.          <2>     9/18/95    ga        
  11.  
  12. */
  13.  
  14.  
  15. #include "ResolveObjectSpecifier.h"
  16. #include "AbstractScriptableObject.h"
  17. #include "Exceptions.h"
  18.  
  19. #include <AEObjects.h>
  20.  
  21.  
  22. //----------------------------------------------------------------------------------------
  23. // ParseObjectSpecifier
  24. //----------------------------------------------------------------------------------------
  25. TAbstractObjectSpecifier* ParseObjectSpecifier(TDescriptor objectSpecifier, DescType desiredClassOfParent /*= typeNull*/, DescType keyFormOfParent /*= typeNull*/, TDescriptor* keyDataOfParent /*= nil*/)
  26.     {
  27.     TAbstractObjectSpecifier* result = nil;
  28.  
  29.     switch(objectSpecifier.DescriptorType())
  30.         {
  31.         case typeObjectSpecifier:
  32.             {
  33.             DescType desiredClass;
  34.             DescType keyForm;
  35.             TDescriptor keyData;
  36.             TDescriptor containerDesc;
  37.             TAbstractObjectSpecifier* containerSpec = nil;
  38.             
  39.             //
  40.             // Extract the parameters from the object specifier
  41.             //
  42.             objectSpecifier.GetObjectSpecifierParameters(desiredClass, keyForm, &keyData, &containerDesc);
  43.             containerSpec = ParseObjectSpecifier(containerDesc, desiredClass, keyForm, &keyData);
  44.             
  45.             //
  46.             // At this point, if keyForm is formTest, then convert it
  47.             // into a whose clause
  48.             //
  49.             if(keyForm == formTest)
  50.                 {
  51.                 TDescriptor testData(keyData);
  52.                 keyForm = formWhose;
  53.                 // take desiredClass, or use desiredClassOfParent?
  54.                 
  55.                 //
  56.                 // If we can collapse the parent specifier into the
  57.                 // formTest, then do so.  The reason we do this is
  58.                 // for performance; if the request is "first item of ... whose",
  59.                 // without collapsing we would first get every
  60.                 // item whose, then extract just the first item.
  61.                 // With collapsing, we can stop searching after we
  62.                 // get the first match.
  63.                 //
  64.                 // n.b. The object support library collapses the
  65.                 // two specifiers together in exactly the same way.
  66.                 //
  67.                 keyData.MakeAERecord();
  68.                 if(keyDataOfParent && ((keyFormOfParent == formAbsolutePosition) || (keyFormOfParent == formRange)))
  69.                     {
  70.                     //
  71.                     // Note:  At this point, the object support library would
  72.                     // convert the formRange descriptor into a simpler descriptor
  73.                     // of type typeWhoseRange, a coerced record that contains parameters
  74.                     // keyAEWhoseRangeStart and keyAEWhoseRangeStop.  The formRange
  75.                     // descriptor is very similar, but it contains keyAERangeStart and
  76.                     // keyAERangeStop parameters, and they are object specifiers whose
  77.                     // key data contains the descriptors that should go into the
  78.                     // keyAEWhoseRangeStart and keyAEWhoseRangeStop parameters.
  79.                     // Rather than bother to extract these parameters at this point
  80.                     // and construct another similar descriptor, we instead do the
  81.                     // extraction when the descriptor is used.
  82.                     //
  83.                     // See TObjectCollector::TObjectCollector for details.
  84.                     //
  85.                     desiredClass = desiredClassOfParent;
  86.                     keyData.PutDescriptorParameter(keyAEIndex, *keyDataOfParent);
  87.                     keyDataOfParent->Dispose();
  88.                     }
  89.                 else
  90.                     {
  91.                     keyData.PutDescTypeParameter(keyAEIndex, kAEAll, typeAbsoluteOrdinal);
  92.                     }
  93.                 keyData.PutDescriptorParameter(keyAETest, testData);
  94.                 keyData.CoerceInPlace(typeWhoseDescriptor);
  95.                 }
  96.             
  97.             //
  98.             // If our desiredClass, keyForm and keyData were rolled
  99.             // into the whose clause formed in 'containerSpec', then
  100.             // do not bother to create a specifier for it.
  101.             //
  102.             if((containerSpec != nil) && (containerSpec->KeyForm() == formWhose) && (keyData.DescriptorType() == typeNull))
  103.                 result = containerSpec;
  104.             else
  105.                 result = new TObjectSpecifier(desiredClass, keyForm, keyData, containerSpec);
  106.             break;
  107.             }
  108.             
  109.         case typeObjectBeingExamined:
  110.             result = new TObjectBeingExamined;
  111.             break;
  112.         
  113.         case typeNull:
  114.             result = nil;
  115.             break;
  116.         
  117.         // typeAEList?
  118.         
  119.         default:
  120.             result = new TArbitrarySpecifier(objectSpecifier);
  121.             break;
  122.         }
  123.     
  124.     return result;
  125.     } // ParseObjectSpecifier
  126.  
  127. //----------------------------------------------------------------------------------------
  128. // ResolveObjectSpecifier
  129. //----------------------------------------------------------------------------------------
  130. TTokenDescriptor ResolveObjectSpecifier(const TAETransaction& t, TDescriptor objectSpecifier, TDescriptor* objectThatCausedError)
  131.     {
  132.     TAbstractObjectSpecifier* parsedSpecifier = nil;
  133.     TAbstractScriptableObject* result = nil;
  134.     TTokenDescriptor resultToken;
  135.     OSErr err = noErr;
  136.     
  137.     NOREGISTER(parsedSpecifier);
  138.     
  139.     Try
  140.         {
  141.         parsedSpecifier = ParseObjectSpecifier(objectSpecifier);
  142.         if(parsedSpecifier == nil)
  143.             FailErr(errAEEventFailed);
  144.         result = parsedSpecifier->ResolveToken(t, nil, objectThatCausedError);
  145.         if(result == nil)
  146.             FailErr(errAENoSuchObject);
  147.         resultToken.AdoptToken(result);
  148.         }
  149.     Catch(err)
  150.         {
  151.         delete parsedSpecifier;
  152.         Throw(err);
  153.         }
  154.     
  155.     return resultToken;
  156.     } // ResolveObjectSpecifier
  157.  
  158. //----------------------------------------------------------------------------------------
  159. // GetNullContainer
  160. //----------------------------------------------------------------------------------------
  161. TAbstractScriptableObject* GetNullContainer()
  162.     {
  163.     TTokenDescriptor nullContainerDesc = CreateNullContainerToken();
  164.     
  165.     return nullContainerDesc.TokenObject();
  166.     } // GetNullContainer
  167.     
  168. //========================================================================================
  169. // Class TAbstractObjectSpecifier
  170. //========================================================================================
  171.  
  172. //----------------------------------------------------------------------------------------
  173. // TAbstractObjectSpecifier::~TAbstractObjectSpecifier
  174. //----------------------------------------------------------------------------------------
  175. TAbstractObjectSpecifier::~TAbstractObjectSpecifier()
  176.     {
  177.     }
  178.  
  179. //----------------------------------------------------------------------------------------
  180. // TAbstractObjectSpecifier::KeyForm
  181. //----------------------------------------------------------------------------------------
  182. DescType TAbstractObjectSpecifier::KeyForm() const
  183.     {
  184.     return typeNull;
  185.     }
  186.     
  187. //----------------------------------------------------------------------------------------
  188. // TAbstractObjectSpecifier::RootContainerIsObjectBeingExamined
  189. //----------------------------------------------------------------------------------------
  190. Boolean TAbstractObjectSpecifier::RootContainerIsObjectBeingExamined() const
  191.     {
  192.     return false;
  193.     }
  194.  
  195. //----------------------------------------------------------------------------------------
  196. // TAbstractObjectSpecifier::ExtractParentSpecifier
  197. //----------------------------------------------------------------------------------------
  198. TAbstractObjectSpecifier* TAbstractObjectSpecifier::ExtractParentSpecifier(DescType& desiredClass, DescType& keyForm, TDescriptor& keyData)
  199.     {
  200.     desiredClass = typeNull;
  201.     keyForm = typeNull;
  202.     keyData.ClearDescriptor();
  203.     
  204.     return nil;
  205.     }
  206.  
  207. //========================================================================================
  208. // Class TObjectSpecifier
  209. //========================================================================================
  210.  
  211. //----------------------------------------------------------------------------------------
  212. // TObjectSpecifier::~TObjectSpecifier
  213. //----------------------------------------------------------------------------------------
  214. TObjectSpecifier::~TObjectSpecifier()
  215.     {
  216.     fKeyData.Dispose();
  217.     delete fContainer;
  218.     if(fCachedToken != nil)
  219.         fCachedToken->DisposeDesignator();
  220.     } // TObjectSpecifier::~TObjectSpecifier
  221.  
  222. //----------------------------------------------------------------------------------------
  223. // TObjectSpecifier::KeyForm
  224. //----------------------------------------------------------------------------------------
  225. DescType TObjectSpecifier::KeyForm() const
  226.     {
  227.     return fKeyForm;
  228.     }
  229.  
  230. //----------------------------------------------------------------------------------------
  231. // TObjectSpecifier::RootContainerIsObjectBeingExamined
  232. //----------------------------------------------------------------------------------------
  233. Boolean TObjectSpecifier::RootContainerIsObjectBeingExamined() const
  234.     {
  235.     if(fContainer == nil)
  236.         return false;
  237.     else
  238.         return fContainer->RootContainerIsObjectBeingExamined();
  239.     }
  240.     
  241. //----------------------------------------------------------------------------------------
  242. // TObjectSpecifier::ExtractParentSpecifier
  243. //----------------------------------------------------------------------------------------
  244. TAbstractObjectSpecifier* TObjectSpecifier::ExtractParentSpecifier(DescType& desiredClass, DescType& keyForm, TDescriptor& keyData)
  245.     {
  246.     TAbstractObjectSpecifier* result = fContainer;
  247.     desiredClass = fDesiredClass;
  248.     keyForm = fKeyForm;
  249.     keyData = fKeyData;
  250.     fContainer = nil;
  251.     
  252.     return result;
  253.     }
  254.  
  255. //----------------------------------------------------------------------------------------
  256. // TObjectSpecifier::BuildObjectSpecifier
  257. //----------------------------------------------------------------------------------------
  258. TDescriptor TObjectSpecifier::BuildObjectSpecifier() const
  259.     {
  260.     TDescriptor result;
  261.     TDescriptor fromContainer;
  262.     
  263.     if(fContainer)
  264.         fromContainer = fContainer->BuildObjectSpecifier();
  265.     
  266.     //
  267.     // If the key form of this specifier is 'typeWhoseDescriptor,' then we
  268.     // need to build a test descriptor 
  269.     //
  270.     if(fKeyForm == formWhose)
  271.         {
  272.         TDescriptor keyDataRecord = fKeyData.Coerce(typeAERecord);
  273.  
  274.         //        
  275.         // Extract keyAETest; this has most of the interesting data for the
  276.         // "formTest" descriptor
  277.         //
  278.         TDescriptor testDesc = keyDataRecord.GetDescriptorParameter(keyAETest);
  279.         result.MakeObjectSpecifier(fDesiredClass, fromContainer, formTest, testDesc, false);
  280.         testDesc.Dispose();
  281.  
  282.         //
  283.         // Extract keyAEIndex:  if it's kAEAll, do nothing; otherwise make another
  284.         // container ospec with MakeObjectSpecifier(fDesiredClass, result,
  285.         // formAbsolutePosition or formRange, key data from keyAEIndex)
  286.         //        
  287.         TDescriptor indexDesc = keyDataRecord.GetDescriptorParameter(keyAEIndex);
  288.         if((indexDesc.DescriptorType() != typeAbsoluteOrdinal) || (indexDesc.GetDescTypeData(typeAbsoluteOrdinal) != kAEAll))
  289.             {
  290.             DescType formOfData = indexDesc.DescriptorType() == typeRangeDescriptor ? formRange : formAbsolutePosition;
  291.             
  292.             TDescriptor tempDesc = result;
  293.             result.MakeObjectSpecifier(fDesiredClass, tempDesc, formOfData, indexDesc, false);
  294.             tempDesc.Dispose();
  295.             }
  296.         indexDesc.Dispose();
  297.         }
  298.     else
  299.         result.MakeObjectSpecifier(fDesiredClass, fromContainer, fKeyForm, fKeyData, false);
  300.     fromContainer.Dispose();
  301.     
  302.     return result;
  303.     } // TObjectSpecifier::BuildObjectSpecifier
  304.  
  305. //----------------------------------------------------------------------------------------
  306. // TObjectSpecifier::ResolveToken
  307. //----------------------------------------------------------------------------------------
  308. TAbstractScriptableObject* TObjectSpecifier::ResolveToken(const TAETransaction& t, TAbstractScriptableObject* objectBeingExamined, TDescriptor* objectThatCausedError /*= nil*/) const
  309.     {
  310.     OSErr err = noErr;
  311.     
  312.     //
  313.     // Don't bother to resolve this token if we've already done it
  314.     // once--just use the object in the cache.
  315.     //
  316.     if((fCachedToken == nil) || (fCachedObjectBeingExamined != objectBeingExamined))
  317.         {
  318.         //
  319.         // First step:  recursively resolve our container token, so
  320.         // we know who to ask to resolve the data in this specifier
  321.         //
  322.         TAbstractScriptableObject* containerToken = nil;
  323.         if(fContainer == nil)
  324.             containerToken = GetNullContainer();
  325.         else
  326.             containerToken = fContainer->ResolveToken(t, objectBeingExamined, objectThatCausedError);
  327.         
  328.         //
  329.         // We really expect the container token to either resolve correctly
  330.         // or fail.
  331.         //
  332.         ASSERT(containerToken);
  333.         if(containerToken != nil)
  334.             {
  335.             //
  336.             // If we have a cached object, get rid of it now
  337.             //
  338.             if(fCachedToken != nil)
  339.                 {
  340.                 ((TObjectSpecifier*)this)->fCachedToken->DisposeDesignator();
  341.                 ((TObjectSpecifier*)this)->fCachedToken = nil;
  342.                 }
  343.             
  344.             //
  345.             // Try to resolve this object specifier
  346.             //
  347.             Try
  348.                 {
  349.                 ((TObjectSpecifier*)this)->fCachedToken = containerToken->Access(t, fDesiredClass, fKeyForm, fKeyData);
  350.                 if(fCachedToken == nil)
  351.                     FailErr(errAENoSuchObject);
  352.                 }
  353.             Catch(err)
  354.                 {
  355.                 if(objectThatCausedError && objectThatCausedError->IsNullDescriptor())
  356.                     {
  357.                     *objectThatCausedError = this->BuildObjectSpecifier();
  358.                     }
  359.                 Throw(err);
  360.                 }
  361.             ((TObjectSpecifier*)this)->fCachedObjectBeingExamined = objectBeingExamined;
  362.             containerToken->DisposeDesignator();
  363.             }
  364.         }
  365.     
  366.     //
  367.     // Return a copy of the cached token
  368.     //
  369.     TAbstractScriptableObject* result = fCachedToken ? fCachedToken->CloneDesignator() : nil;
  370.  
  371.     return result;
  372.     } // TObjectSpecifier::ResolveToken
  373.  
  374. //========================================================================================
  375. // Class TObjectBeingExamined
  376. //========================================================================================
  377.  
  378. //----------------------------------------------------------------------------------------
  379. // TObjectBeingExamined::KeyForm
  380. //----------------------------------------------------------------------------------------
  381. DescType TObjectBeingExamined::KeyForm() const
  382.     {
  383.     //
  384.     // Special flag to identify a TObjectBeingExamined
  385.     //
  386.     return typeObjectBeingExamined;
  387.     }
  388.  
  389. //----------------------------------------------------------------------------------------
  390. // TObjectBeingExamined::RootContainerIsObjectBeingExamined
  391. //----------------------------------------------------------------------------------------
  392. Boolean TObjectBeingExamined::RootContainerIsObjectBeingExamined() const
  393.     {
  394.     return true;
  395.     }
  396.  
  397. //----------------------------------------------------------------------------------------
  398. // TObjectBeingExamined::BuildObjectSpecifier
  399. //----------------------------------------------------------------------------------------
  400. TDescriptor TObjectBeingExamined::BuildObjectSpecifier() const
  401.     {
  402.     TDescriptor result;
  403.     
  404.     //
  405.     // 'objectBeingExamined' is a special object specifier that only
  406.     // has meaning in the context of a comparison descriptor.
  407.     //
  408.     result.SetDescriptorDataTypeObjectBeingExamined();
  409.     
  410.     return result;
  411.     }
  412.     
  413. //----------------------------------------------------------------------------------------
  414. // TObjectBeingExamined::ResolveToken
  415. //----------------------------------------------------------------------------------------
  416. TAbstractScriptableObject* TObjectBeingExamined::ResolveToken(const TAETransaction&, TAbstractScriptableObject* objectBeingExamined, TDescriptor* /*objectThatCausedError = nil*/) const
  417.     {
  418.     REQUIREVALIDPOINTER(objectBeingExamined);
  419.     return objectBeingExamined->CloneDesignator();
  420.     } // TObjectBeingExamined::ResolveToken
  421.  
  422.  
  423. //========================================================================================
  424. // Class TArbitrarySpecifier
  425. //========================================================================================
  426.  
  427. //----------------------------------------------------------------------------------------
  428. // TArbitrarySpecifier::~TArbitrarySpecifier
  429. //----------------------------------------------------------------------------------------
  430. TArbitrarySpecifier::~TArbitrarySpecifier()
  431.     {
  432.     fKeyData.Dispose();
  433.     } // TArbitrarySpecifier::~TArbitrarySpecifier
  434.  
  435. //----------------------------------------------------------------------------------------
  436. // TArbitrarySpecifier::BuildObjectSpecifier
  437. //----------------------------------------------------------------------------------------
  438. TDescriptor TArbitrarySpecifier::BuildObjectSpecifier() const
  439.     {
  440.     TDescriptor result;
  441.     TDescriptor nullContainer;
  442.     
  443.     result.MakeObjectSpecifier(typeWildCard, nullContainer, fKeyData.DescriptorType(), fKeyData, false);
  444.     
  445.     return result;
  446.     } // TArbitrarySpecifier::BuildObjectSpecifier
  447.  
  448. //----------------------------------------------------------------------------------------
  449. // TArbitrarySpecifier::ResolveToken
  450. //----------------------------------------------------------------------------------------
  451. TAbstractScriptableObject* TArbitrarySpecifier::ResolveToken(const TAETransaction& t, TAbstractScriptableObject* /*objectBeingExamined*/, TDescriptor* objectThatCausedError /*= nil*/) const
  452.     {
  453.     TAbstractScriptableObject* result = nil;
  454.     OSErr err = noErr;
  455.     
  456.     //
  457.     // If we attempt to resolve a descriptor that is NOT an object
  458.     // specifier, then we will pass it to the null container's
  459.     // access method, using:
  460.     //
  461.     //        desired class = typeWildCard
  462.     //        key form = descriptor type of the descriptor being resolved
  463.     //        key data = the descriptor being resolved
  464.     //
  465.     // If the descriptor type is unknown, then the null container
  466.     // will no doubt return errAEBadKeyForm.
  467.     //    
  468.     TAbstractScriptableObject* nullContainer = GetNullContainer();
  469.     Try
  470.         {
  471.         result = nullContainer->Access(t, typeWildCard, fKeyData.DescriptorType(), fKeyData);
  472.         }
  473.     Catch(err)
  474.         {
  475.         if(objectThatCausedError && objectThatCausedError->IsNullDescriptor())
  476.             {
  477.             objectThatCausedError->SetDescriptorData(fKeyData);
  478.             }
  479.         nullContainer->DisposeDesignator();
  480.         Throw(err);
  481.         }
  482.     nullContainer->DisposeDesignator();
  483.     
  484.     return result;
  485.     } // TArbitrarySpecifier::ResolveToken
  486.  
  487.